﻿using System.ComponentModel;
using System.Linq;
using System.Windows;
using Fayshine.VA.Helpers;
using Fayshine.VA.RIAService.Web;
using Fayshine.VA.Controls;
using Fayshine.VA.Models;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System;
using System.Threading;
using System.Text;
using System.Diagnostics;

namespace Fayshine.VA.ViewModels
{
    public class StatisticsReportViewModel : INotifyPropertyChanged
    {
        #region Private Fields

        private FayshineDomainContext m_Context = null;

        private string m_CurveTitle = string.Empty;
        public event ResetHistoryChartEventHandler ResetHisotryChartEvent;
        public event AppendHistoryPassengerFlowEventHandler AppendHistoryPassengerFlow;
        public event AppendMultiHistoryPassengerEventHandler AppendMultiHistoryPassenger;

        private List<AreaExtend> m_checkedAreas;

        private List<MonitorAreaGateExt> m_checkedGates;

        #endregion

        #region Properties

        public ObservableCollection<AreaExtend> AreaExtends
        {
            get;
            set;
        }

        public ObservableCollection<MonitorAreaGateExt> MonitorAreaGateExts
        {
            get;
            set;
        }

        public ObservableCollection<AreaExtend> AreaExtends2
        {
            get;
            set;
        }

        public ObservableCollection<MonitorAreaGateExt> MonitorAreaGateExts2
        {
            get;
            set;
        }

        public IEnumerable<passengerflowbymin> TempPassengerFlowByMin
        {
            get;
            set;
        }

        public IEnumerable<passengerflowbydate> TempPassengerFlowByDate
        {
            set;
            get;
        }

        public List<ComparePassengerFlow> ComparePassengerFlows
        {
            get;
            set;
        }

        public IEnumerable<passengerflowbyage> TempPassengerAges
        {
            get;
            set;
        }

        public string CurveTitle
        {
            get
            {
                return m_CurveTitle;
            }
            set
            {
                m_CurveTitle = value;
                NofityPropertyChanged("CurveTitle");
            }
        }

        public List<AreaExtend> CheckedAreas
        {
            get { return m_checkedAreas; }
        }

        public List<MonitorAreaGateExt> CheckedGates
        {
            get { return m_checkedGates; }
        }

        public List<HistoryPassengerFlow> TempHistoryPassengerFlow
        {
            get;
            set;
        }

        #endregion

        public StatisticsReportViewModel()
        {
            this.MonitorAreaGateExts = new ObservableCollection<MonitorAreaGateExt>();
            this.AreaExtends = new ObservableCollection<AreaExtend>();
            this.AreaExtends2 = new ObservableCollection<AreaExtend>();
            this.MonitorAreaGateExts2 = new ObservableCollection<MonitorAreaGateExt>();
            m_Context = new FayshineDomainContext();
        }

        #region Public methods

        public void GetAllAreas()
        {
            var getAreasQuery = m_Context.GetAreasQuery();
            var loadShopsOperation = m_Context.Load(getAreasQuery, (s) =>
            {
                if (!s.HasError)
                {
                    AreaExtend tempAreaExt = null;
                    AreaExtend tempAreaExt2 = null;
                    s.Entities.ToList().ForEach(e =>
                    {
                        tempAreaExt = new AreaExtend();
                        tempAreaExt.ID = e.ID;
                        tempAreaExt.Name = e.Name;
                        tempAreaExt.Tag = e;
                        tempAreaExt.IsSelected = false;
                        this.AreaExtends.Add(tempAreaExt);

                        tempAreaExt2 = new AreaExtend();
                        tempAreaExt2.ID = e.ID;
                        tempAreaExt2.Name = e.Name;
                        tempAreaExt2.Tag = e;
                        tempAreaExt2.IsSelected = false;
                        this.AreaExtends2.Add(tempAreaExt2);
                    });
                }
                else
                {
                    MessageBox.Show(s.Error.Message + s.Error.StackTrace);
                }
                BusyIndicator indicator = Application.Current.RootVisual as BusyIndicator;
                indicator.IsBusy = false;
            }, true);
        }

        public void SelectAreasChanged(List<area> areas)
        {
            if (areas.Count > 0)
            {
                this.MonitorAreaGateExts.Clear();
                MonitorAreaGateExt tempMonitorExt;
                if (areas.Count == 1)
                {
                    MonitorAreaGateExt topMonitorExt = new MonitorAreaGateExt();
                    topMonitorExt.ID = areas[0].ID;
                    topMonitorExt.Name = "全部";
                    topMonitorExt.ParentID = areas[0].ParentID;
                    topMonitorExt.TypeID = 1;
                    topMonitorExt.IsSelected = true;
                    this.MonitorAreaGateExts.Add(topMonitorExt);

                    areas[0].gates.OrderBy(o => o.ID).each(e =>
                    {
                        tempMonitorExt = new MonitorAreaGateExt();
                        tempMonitorExt.ID = e.ID;
                        tempMonitorExt.ParentID = areas[0].ID;
                        tempMonitorExt.Name = e.Name;
                        tempMonitorExt.TypeID = 0;
                        tempMonitorExt.ParentMonitor = topMonitorExt;
                        tempMonitorExt.IsSelected = true;
                        topMonitorExt.Childs.Add(tempMonitorExt);
                        this.MonitorAreaGateExts.Add(tempMonitorExt);
                    });

                }
                else
                {
                    areas.each(a =>
                    {
                        tempMonitorExt = new MonitorAreaGateExt();
                        tempMonitorExt.ID = a.ID;
                        tempMonitorExt.Name = a.Name;
                        tempMonitorExt.ParentID = a.ParentID;
                        tempMonitorExt.TypeID = 1;
                        this.MonitorAreaGateExts.Add(tempMonitorExt);
                    });

                    tempMonitorExt = new MonitorAreaGateExt();
                    tempMonitorExt.ID = -1;
                    tempMonitorExt.Name = "所选店铺总和";
                    tempMonitorExt.ParentID = null;
                    tempMonitorExt.TypeID = 2;
                    this.MonitorAreaGateExts.Add(tempMonitorExt);
                }

            }
        }

        public void SelectAreasChanged2(List<area> areas)
        {
            if (areas.Count > 0)
            {
                this.MonitorAreaGateExts2.Clear();
                MonitorAreaGateExt tempMonitorExt;
                if (areas.Count == 1)
                {
                    MonitorAreaGateExt topMonitorExt = new MonitorAreaGateExt();
                    topMonitorExt.ID = areas[0].ID;
                    topMonitorExt.Name = "全部";
                    topMonitorExt.ParentID = areas[0].ParentID;
                    topMonitorExt.TypeID = 1;
                    topMonitorExt.IsSelected = true;
                    this.MonitorAreaGateExts2.Add(topMonitorExt);

                    areas[0].gates.OrderBy(o => o.ID).each(e =>
                    {
                        tempMonitorExt = new MonitorAreaGateExt();
                        tempMonitorExt.ID = e.ID;
                        tempMonitorExt.ParentID = areas[0].ID;
                        tempMonitorExt.Name = e.Name;
                        tempMonitorExt.TypeID = 0;
                        tempMonitorExt.ParentMonitor = topMonitorExt;
                        tempMonitorExt.IsSelected = true;
                        topMonitorExt.Childs.Add(tempMonitorExt);
                        this.MonitorAreaGateExts2.Add(tempMonitorExt);
                    });

                }
                else
                {
                    areas.each(a =>
                    {
                        tempMonitorExt = new MonitorAreaGateExt();
                        tempMonitorExt.ID = a.ID;
                        tempMonitorExt.Name = a.Name;
                        tempMonitorExt.ParentID = a.ParentID;
                        tempMonitorExt.TypeID = 1;
                        this.MonitorAreaGateExts2.Add(tempMonitorExt);
                    });

                    tempMonitorExt = new MonitorAreaGateExt();
                    tempMonitorExt.ID = -1;
                    tempMonitorExt.Name = "所选店铺总和";
                    tempMonitorExt.ParentID = null;
                    tempMonitorExt.TypeID = 2;
                    this.MonitorAreaGateExts2.Add(tempMonitorExt);
                }

            }
        }

        public List<HistoryPassengerFlow> GetHistoryPassengerByWeek(bool isAvg,DateTime startTime, DateTime endTime, List<DayOfWeek> enbaleWeeks)
        {
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            var firstDurationPassengers = GetAnyDurationHistoryPassengerFlow(isSingleArea, this.TempPassengerFlowByMin, startTime, endTime, enbaleWeeks);

            return CombineHistoryPassengerFlow2OneDay(isAvg, firstDurationPassengers);
        }

        public List<HistoryPassengerFlow> CompoundHistoryPassengerAndPos(bool isAvg, List<HistoryPassengerFlow> historyPassengerFlow, List<posbymin> possbyMins)
        {
            List<HistoryPassengerFlow> computedHistoryPassengerFlow = new List<HistoryPassengerFlow>();

            DateTime startTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);
            DateTime endTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59);
            decimal percent = 0;
            while (startTime < endTime)
            {
                HistoryPassengerFlow tempPassgnegerFlow = new HistoryPassengerFlow();
                //historyPassengerFlow.DisplayTitle = dtRangeStart.ToShortDateString() + " 至 " + dtRangeEnd.ToShortDateString();
                tempPassgnegerFlow.HistoryTime = startTime;
                tempPassgnegerFlow.DisplayValue = string.Format("{0:HH:mm}", startTime);
                IEnumerable<int> inCounts = from t in historyPassengerFlow
                                            where t.HistoryTime.Hour == startTime.Hour &&
                                                  t.HistoryTime.Minute == startTime.Minute &&
                                                  t.HistoryTime.Second == startTime.Second
                                            select t.InCount;
                IEnumerable<int> outCounts = from t in historyPassengerFlow
                                             where t.HistoryTime.Hour == startTime.Hour &&
                                                 t.HistoryTime.Minute == startTime.Minute &&
                                                 t.HistoryTime.Second == startTime.Second
                                             select t.OutCount;
                IEnumerable<int> strandedCount = from t in historyPassengerFlow
                                                 where t.HistoryTime.Hour == startTime.Hour &&
                                                  t.HistoryTime.Minute == startTime.Minute &&
                                                  t.HistoryTime.Second == startTime.Second
                                                 select t.StrandedCount;
                IEnumerable<int> tradeMoneys = from t in possbyMins
                                               where t.dt.Hour == startTime.Hour &&
                                                 t.dt.Minute == startTime.Minute &&
                                                 t.dt.Second == startTime.Second
                                               select t.TradeMoney;
                IEnumerable<int> tradeCounts = from t in possbyMins
                                               where t.dt.Hour == startTime.Hour &&
                                                 t.dt.Minute == startTime.Minute &&
                                                 t.dt.Second == startTime.Second
                                               select t.TradeCount;

                tempPassgnegerFlow.InCount = inCounts.Any() ? (isAvg ? Convert.ToInt32(inCounts.Average()) : inCounts.Sum()) : 0;
                tempPassgnegerFlow.OutCount = outCounts.Any() ? (isAvg ? Convert.ToInt32(outCounts.Average()) : outCounts.Sum()) : 0;

                tempPassgnegerFlow.StrandedCount = strandedCount.Any() ? (isAvg ? Convert.ToInt32(strandedCount.Average()) : strandedCount.Sum()) : 0;

                tempPassgnegerFlow.TradeCount = tradeCounts.Any() ? (isAvg ? Convert.ToInt32(tradeCounts.Average()) : tradeCounts.Sum()) : 0;
                tempPassgnegerFlow.TradeMoney = tradeMoneys.Any() ? (isAvg ? Convert.ToInt32(tradeMoneys.Average()) : tradeMoneys.Sum()) : 0;

                percent = tempPassgnegerFlow.TradeCount > 0 ? (decimal)tempPassgnegerFlow.TradeMoney / tempPassgnegerFlow.TradeCount : 0;
                percent = Math.Round(percent, 2);
                tempPassgnegerFlow.AvgTradeMoney = percent.ToString();

                percent = tempPassgnegerFlow.InCount > 0 ? ((decimal)tempPassgnegerFlow.TradeCount / tempPassgnegerFlow.InCount) * 100 : 0;
                percent = Math.Round(percent, 2);

                tempPassgnegerFlow.SalePercent = Convert.ToDouble(percent / 100);

                computedHistoryPassengerFlow.Add(tempPassgnegerFlow);
                startTime = startTime.AddMinutes(30);

            }

            return computedHistoryPassengerFlow;
        }

        #endregion

        #region 日报表分析

        public void RefreshDayReport(bool isIn, DateTime dateTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;

            DateTime startTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 0, 0, 0);
            DateTime endTime = startTime.AddDays(1);//new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59);

            var getDurationPassengerQuery = m_Context.GetPassengerflowbySpecifiedTimeQuery(monitorAreaIDs, 30, startTime, endTime);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (a) =>
            {
                if (!a.HasError)
                {
                    var dayGatePassenger = GetGateDayPassengerFlow(isSingleArea, a.Entities.ToList(), startTime, endTime);
                    var dayDurationPassengers = GetAnyDurationHistoryPassengerFlow(isSingleArea, a.Entities, startTime, endTime, null);

                    this.TempPassengerFlowByMin = a.Entities;

                    var getPassengerAge = m_Context.GetPassengerflowagebySpecifiedTimeQuery(monitorAreaIDs, startTime, endTime);
                    var loadPassengerAge = m_Context.Load(getPassengerAge, (b) => {

                        if (!b.HasError)
                        {
                            this.TempPassengerAges = b.Entities;
                            var getYearDayPassengerQuery = m_Context.GetPassengerflowByYearDayQuery(monitorAreaIDs, dateTime.Year);

                            var loadMonthPassgnerQuery = m_Context.Load(getYearDayPassengerQuery, (c) =>
                            {
                                if (!c.HasError)
                                {
                                    var yearDayPassneger = GetYearDayHistoryPassengerFlow(isSingleArea,c.Entities, dateTime.Year);
                                    this.TempPassengerFlowByDate = c.Entities;

                                    var getPosQuery = m_Context.GetPosDataBySpecifiedTimeQuery(monitorAreaIDs, 30, startTime, endTime);
                                    var lodPosQuery = m_Context.Load(getPosQuery, (d) => {

                                        if (!d.HasError)
                                        {
                                            if (AppendMultiHistoryPassenger != null)
                                            {
                                                AppendMultiHistoryPassenger(string.Empty, true,
                                                                            dayGatePassenger,
                                                                            dayDurationPassengers,
                                                                            yearDayPassneger,
                                                                            CompoundHistoryPassengerAndPos(false, dayDurationPassengers, d.Entities.ToList()));
                                            }
                                        }
                                    
                                    }, true);
                                }
                            }, true);
                        }
                    
                    }, true);
                   
                }
            
            }, true);
        }

        private List<HistoryPassengerFlow> GetGateDayPassengerFlow(bool isSingleArea, List<passengerflowbymin> passengerflows, DateTime startTime, DateTime endTime)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            HistoryPassengerFlow temHistoryPassengerFlow = null;
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    ids.each(id =>
                    {
                        var tempPassengerFlows = passengerflows.Where(entity => id == entity.gateID).ToList();
                        temHistoryPassengerFlow = ConvertGateDayHistoryPassengerFlow(tempPassengerFlows, startTime, endTime);
                        if (temHistoryPassengerFlow != null)
                        {
                            temHistoryPassengerFlow.DisplayTitle = GetGateName(id);
                            historyPassengerFlows.Add(temHistoryPassengerFlow);
                        }
                    });
                }
            }
            else
            {
                var selectAreaExts = this.AreaExtends.Where(a => a.IsSelected).ToList();
                selectAreaExts.each(s =>
                {
                    var ids = GetGateIDsByArea(s.ID);
                    var tempPassengerFlows = passengerflows.Where(entity => ids.Contains(entity.gateID)).ToList();
                    temHistoryPassengerFlow = ConvertGateDayHistoryPassengerFlow(tempPassengerFlows, startTime, endTime);
                    if (temHistoryPassengerFlow != null)
                    {
                        temHistoryPassengerFlow.DisplayTitle = s.Name;
                        historyPassengerFlows.Add(temHistoryPassengerFlow);
                    }
                });
            }

            return historyPassengerFlows;
        }

        private HistoryPassengerFlow ConvertGateDayHistoryPassengerFlow(List<passengerflowbymin> passengerflows, DateTime startTime, DateTime endTime)
        {
            HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();

            IEnumerable<int?> inCounts = from t in passengerflows
                                         where t.isIn == true && t.dt >= startTime
                                               && t.dt < endTime
                                         select t.count;
            IEnumerable<int?> outCounts = from t in passengerflows
                                          where t.isIn == false && t.dt >= startTime
                                               && t.dt < endTime
                                          select t.count;

            historyPassengerFlow.InCount = inCounts.Sum().Value;
            historyPassengerFlow.OutCount = outCounts.Sum().Value;
            historyPassengerFlow.StrandedCount = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
            historyPassengerFlow.AllInOut = historyPassengerFlow.InCount + historyPassengerFlow.OutCount;
            historyPassengerFlow.Differ = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;

            return historyPassengerFlow;
        }

        public List<HistoryPassengerFlow> GetPassengerflowsBySex(DateTime startTime,DateTime endTime)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbyage> tempPassengerFlows = new List<passengerflowbyage>();

            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;

            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = this.TempPassengerAges.Where(entity => ids.Contains(entity.GateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = this.TempPassengerAges.ToList();
            }


            if (tempPassengerFlows.Any())
            {
                HistoryPassengerFlow manHistoryPassengerFlow = new HistoryPassengerFlow();
                manHistoryPassengerFlow.SexName = "男";
                IEnumerable<int> manCounts = from t in tempPassengerFlows
                                             where t.HistoryTime >= startTime && t.HistoryTime < endTime && t.Gender == true
                                             select t.Count;

                manHistoryPassengerFlow.AllInOut = manCounts.Sum();
                historyPassengerFlows.Add(manHistoryPassengerFlow);

                HistoryPassengerFlow womanHistoryPassengerFlow = new HistoryPassengerFlow();
                womanHistoryPassengerFlow.SexName = "女";
                IEnumerable<int> womanCounts = from t in tempPassengerFlows
                                               where t.HistoryTime >= startTime && t.HistoryTime < endTime && t.Gender == false
                                               select t.Count;
                womanHistoryPassengerFlow.AllInOut = womanCounts.Sum();

                historyPassengerFlows.Add(womanHistoryPassengerFlow);


            }
            else
            {
                HistoryPassengerFlow manHistoryPassengerFlow = new HistoryPassengerFlow();
                manHistoryPassengerFlow.SexName = "男";
                manHistoryPassengerFlow.AllInOut = 0;
                historyPassengerFlows.Add(manHistoryPassengerFlow);
                HistoryPassengerFlow womanHistoryPassengerFlow = new HistoryPassengerFlow();
                womanHistoryPassengerFlow.SexName = "女";
                womanHistoryPassengerFlow.AllInOut = 0;
                historyPassengerFlows.Add(womanHistoryPassengerFlow);
            }
            return historyPassengerFlows;
        }

        public List<HistoryPassengerFlow> GetAgeDurationPassengerFlow(DateTime startTime, DateTime endTime)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbyage> tempPassengerFlows = new List<passengerflowbyage>();

            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;

            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = this.TempPassengerAges.Where(entity => ids.Contains(entity.GateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = this.TempPassengerAges.ToList();
            }

            historyPassengerFlows = ConvertToAgeDurationPassengerFlow(tempPassengerFlows, startTime, endTime);

            return historyPassengerFlows;
        }

        public List<HistoryPassengerFlow> GetYearPassengerflowsByArea(int areaID,int year)
        {
            List<HistoryPassengerFlow> passengers = new List<HistoryPassengerFlow>();

            List<int> gateIds = GetGateIDsByArea(areaID);
            var areaPassengers = this.TempPassengerFlowByDate.Where(t => gateIds.Contains(t.gateID));

            passengers = GetYearDayHistoryPassengerFlow(false, areaPassengers, year);

            return passengers;
        }

        public List<HistoryPassengerFlow> GetDayDurationPassengerByArea(int areaID,DateTime dateTime)
        {
            List<HistoryPassengerFlow> passengers = new List<HistoryPassengerFlow>();

            List<int> gateIds = GetGateIDsByArea(areaID);
            var areaPassengers = this.TempPassengerFlowByMin.Where(t => gateIds.Contains(t.gateID));

            DateTime startTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 0, 0, 0);
            DateTime endTime = startTime.AddDays(1);

            passengers = GetAnyDurationHistoryPassengerFlow(false, areaPassengers, startTime, endTime, null);

            return passengers;
        }

        private List<HistoryPassengerFlow> ConvertToAgeDurationPassengerFlow(List<passengerflowbyage> passengerFlowAges, DateTime startTime, DateTime endTime)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            int tempAge = 5;
            HistoryPassengerFlow tempHistoryPassengerFlow = null;
            
            while (tempAge <= 120)
            {
                tempHistoryPassengerFlow = new HistoryPassengerFlow();
                tempHistoryPassengerFlow.Age = tempAge;
                IEnumerable<int> counts = from t in passengerFlowAges
                                          where t.HistoryTime >= startTime && t.HistoryTime < endTime && t.Age == tempAge
                                          select t.Count;
                tempHistoryPassengerFlow.AllInOut = counts.Sum();
                tempHistoryPassengerFlow.DisplayTitle = (tempAge - 4) + "岁-" + tempAge + "岁";
                historyPassengerFlows.Add(tempHistoryPassengerFlow);
                tempAge += 5;
            }
            return historyPassengerFlows;
        }

        #endregion

        #region 周报表分析

        public void RefreshWeekReport(bool isIn, DateTime dateTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            this.CurveTitle = GetMonthReportTitle(isSingleArea, isIn, dateTime);

            var getWeekDayPassengerQuery = m_Context.GetPassengerflowByWeekQuery(monitorAreaIDs, dateTime);

            var loadMonthPassgnerQuery = m_Context.Load(getWeekDayPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    DateTime startTime = dateTime;
                    DateTime endTime = dateTime;
                    GetWeekStartAndEndTime(dateTime, out startTime, out endTime);
                    var thisWeekDayPassneger = GetWeekDayPassengerFlow(isSingleArea, s.Entities, startTime, endTime);
                    var thisWeekGatePassenger = GetGateWeekDayPassengerFlow(isSingleArea, s.Entities.ToList(), startTime, endTime);

                    DateTime lastStartTime = dateTime.AddDays(-7);
                    DateTime lastEndTime = dateTime.AddDays(-7);
                    GetWeekStartAndEndTime(dateTime.AddDays(-7), out lastStartTime, out lastEndTime);
                    var lastWeekDayPassenger = GetWeekDayPassengerFlow(isSingleArea, s.Entities, lastStartTime, lastEndTime);

                    DateTime lastYearStartTime = dateTime.AddYears(-1);
                    DateTime lastYearEndTime = dateTime.AddYears(-1);
                    GetWeekStartAndEndTime(dateTime.AddYears(-1), out lastYearStartTime, out lastYearEndTime);
                    var lastYearWeekDayPassenger = GetWeekDayPassengerFlow(isSingleArea, s.Entities, lastYearStartTime, lastYearEndTime);
                   
                    m_Context.passengerflowbydates.Clear();

                    var getYearWeekPassengerQuery = m_Context.GetPassengerflowByYearWeekQuery(monitorAreaIDs, dateTime.Year);

                    var loadYearPassgnerQuery = m_Context.Load(getYearWeekPassengerQuery, (t) =>
                    {
                        if (!t.HasError)
                        {
                            var thisYearWeekPassneger = GetYearWeekPassengerFlow(isSingleArea, t.Entities, dateTime.Year);
                            var lastYearWeekPassenger = GetYearWeekPassengerFlow(isSingleArea, t.Entities, dateTime.Year - 1);

                            var getPassengerAgeFlowQuery = m_Context.GetPassengerFlowAgesByWeekQuery(monitorAreaIDs, dateTime);
                            var loadPassengerAgeFlowQuery = m_Context.Load(getPassengerAgeFlowQuery, (d) => {

                                if (!d.HasError)
                                {
                                    this.TempPassengerAges = d.Entities;
                                }
                                if (AppendMultiHistoryPassenger != null)
                                {
                                    AppendMultiHistoryPassenger(this.CurveTitle, isIn,
                                                                thisWeekDayPassneger,
                                                                lastWeekDayPassenger,
                                                                lastYearWeekDayPassenger,
                                                                thisYearWeekPassneger,
                                                                lastYearWeekPassenger,
                                                                thisWeekGatePassenger);
                                }
                            
                            }, true);
                        }
                    }, true);
                }
            }, true);

            //Set DateTime Query, 周每半小时统计
            DateTime startDayTime = dateTime;
            DateTime endDayTime = dateTime;
            GetWeekStartAndEndTime(dateTime, out startDayTime, out endDayTime);
            var getDurationPassengerQuery = m_Context.GetPassengerflowbySpecifiedTimeQuery(monitorAreaIDs, 30, startDayTime, endDayTime);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (a) =>
            {
                if (!a.HasError)
                {
                    var firstDurationPassengers = GetAnyDurationHistoryPassengerFlow(isSingleArea, a.Entities, startDayTime, endDayTime, null);
                   this.TempPassengerFlowByMin = a.Entities;
                    if (AppendHistoryPassengerFlow != null)
                    {
                       AppendHistoryPassengerFlow(string.Empty, isIn,
                                                   CombineHistoryPassengerFlow2OneDay(false, firstDurationPassengers), null);
                    }

                }
            }, true);

        }

        public List<HistoryPassengerFlow> GetWeekAnyDuarationPassengersByArea(int areaID, DateTime dateTime)
        {
            List<HistoryPassengerFlow> passengers = new List<HistoryPassengerFlow>();

            List<int> gateIds = GetGateIDsByArea(areaID);
            var areaPassengers = this.TempPassengerFlowByMin.Where(t => gateIds.Contains(t.gateID));
            DateTime startDayTime = dateTime;
            DateTime endDayTime = dateTime;
            GetWeekStartAndEndTime(dateTime, out startDayTime, out endDayTime);

            passengers = GetAnyDurationHistoryPassengerFlow(false, areaPassengers, startDayTime, endDayTime, null);

            return passengers;
        }

        public List<HistoryPassengerFlow> GetWeekDayPassengerFlow(bool isSingleArea, IEnumerable<passengerflowbydate> entities, DateTime startTime, DateTime endTime)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbydate> tempPassengerFlows = new List<passengerflowbydate>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            historyPassengerFlows = ConvertWeekDayHistoryPassengerFlow(tempPassengerFlows, startTime, endTime);
            return historyPassengerFlows;
        }

        private List<HistoryPassengerFlow> ConvertWeekDayHistoryPassengerFlow(List<passengerflowbydate> passengerflows,DateTime startTime,DateTime endTime)
        {
            List<HistoryPassengerFlow> weekDaysPassengerFlow = new List<HistoryPassengerFlow>();
            int lastInCount = 0;
            int lastOutCount = 0;
            while (startTime < endTime)
            {
                HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();

                historyPassengerFlow.HistoryTime = startTime;
                historyPassengerFlow.DisplayTitle = FayshineManager.Instance.GetWeekDayString(startTime.DayOfWeek);
                historyPassengerFlow.MonthOrDayOrWeek = FayshineManager.Instance.GetWeekDayNumber(startTime.DayOfWeek);
                IEnumerable<int?> inCounts = from t in passengerflows
                                             where t.dt.Value == historyPassengerFlow.MonthOrDayOrWeek && t.historytime.Value.Month == startTime.Month
                                                   && t.historytime.Value.Year == startTime.Year && t.historytime.Value.Day == startTime.Day && t.isIn == true
                                             select t.count;
                IEnumerable<int?> outCounts = from t in passengerflows
                                              where t.dt.Value == historyPassengerFlow.MonthOrDayOrWeek && t.historytime.Value.Month == startTime.Month
                                                    && t.historytime.Value.Year == startTime.Year && t.historytime.Value.Day == startTime.Day && t.isIn == false
                                              select t.count;

                historyPassengerFlow.InCount = inCounts.Sum().Value;
                historyPassengerFlow.OutCount = outCounts.Sum().Value;
                historyPassengerFlow.AccumulateInCount = lastInCount + historyPassengerFlow.InCount;
                historyPassengerFlow.AccumulateOutCount = lastInCount + historyPassengerFlow.OutCount;
                historyPassengerFlow.StrandedCount = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                historyPassengerFlow.AllInOut = historyPassengerFlow.InCount + historyPassengerFlow.OutCount;
                historyPassengerFlow.Differ = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                lastInCount = historyPassengerFlow.AccumulateInCount;
                lastOutCount = historyPassengerFlow.AccumulateOutCount;

                weekDaysPassengerFlow.Add(historyPassengerFlow);
                startTime = startTime.AddDays(1);

            }

            return weekDaysPassengerFlow;
        }

        private List<HistoryPassengerFlow> GetYearWeekPassengerFlow(bool isSingleArea, IEnumerable<passengerflowbydate> entities, int year)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbydate> tempPassengerFlows = new List<passengerflowbydate>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            historyPassengerFlows = ConvertYearWeekHistoryPassengerFlow(tempPassengerFlows, year);
            return historyPassengerFlows;
        }

        private List<HistoryPassengerFlow> ConvertYearWeekHistoryPassengerFlow(List<passengerflowbydate> passengerflows, int year)
        {
            List<HistoryPassengerFlow> yearWeeksPassengerFlow = new List<HistoryPassengerFlow>();
            int firstWeek = 1;
            int endWeek = FayshineManager.Instance.GetYearWeekCount(year);
            int lastInCount = 0;
            int lastOutCount = 0;
            while (firstWeek <= endWeek)
            {
                HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();

                //historyPassengerFlow.HistoryTime = startTime;
                // historyPassengerFlow.DisplayTitle = FayshineManager.Instance.GetWeekDayString(startTime
                historyPassengerFlow.MonthOrDayOrWeek = firstWeek;
                IEnumerable<int?> inCounts = from t in passengerflows
                                             where t.dt.Value == firstWeek && t.historytime.Value.Year == year && t.isIn == true
                                             select t.count;
                IEnumerable<int?> outCounts = from t in passengerflows
                                              where t.dt.Value == firstWeek && t.historytime.Value.Year == year && t.isIn == false
                                              select t.count;

                historyPassengerFlow.InCount = inCounts.Sum().Value;
                historyPassengerFlow.OutCount = outCounts.Sum().Value;
                historyPassengerFlow.AccumulateInCount = lastInCount + historyPassengerFlow.InCount;
                historyPassengerFlow.AccumulateOutCount = lastInCount + historyPassengerFlow.OutCount;
                historyPassengerFlow.StrandedCount = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                historyPassengerFlow.AllInOut = historyPassengerFlow.InCount + historyPassengerFlow.OutCount;
                historyPassengerFlow.Differ = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                lastInCount = historyPassengerFlow.AccumulateInCount;
                lastOutCount = historyPassengerFlow.AccumulateOutCount;

                yearWeeksPassengerFlow.Add(historyPassengerFlow);
                firstWeek++;
            }

            return yearWeeksPassengerFlow;
        }

        private List<HistoryPassengerFlow> GetGateWeekDayPassengerFlow(bool isSingleArea, List<passengerflowbydate> passengerflows, DateTime startTime, DateTime endTime)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            HistoryPassengerFlow temHistoryPassengerFlow = null;
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    ids.each(id =>
                    {
                        var tempPassengerFlows = passengerflows.Where(entity => id == entity.gateID).ToList();
                        temHistoryPassengerFlow = ConvertGateDayHistoryPassengerFlow(tempPassengerFlows, startTime,endTime);
                        if (temHistoryPassengerFlow != null)
                        {
                            temHistoryPassengerFlow.DisplayTitle = GetGateName(id);
                            historyPassengerFlows.Add(temHistoryPassengerFlow);
                        }

                    });
                }
            }
            else
            {
                var selectAreaExts = this.AreaExtends.Where(a => a.IsSelected).ToList();
                selectAreaExts.each(s =>
                {
                    var ids = GetGateIDsByArea(s.ID);
                    var tempPassengerFlows = passengerflows.Where(entity => ids.Contains(entity.gateID)).ToList();
                    temHistoryPassengerFlow = ConvertGateDayHistoryPassengerFlow(tempPassengerFlows, startTime,endTime);
                    if (temHistoryPassengerFlow != null)
                    {
                        temHistoryPassengerFlow.DisplayTitle = s.Name;
                        historyPassengerFlows.Add(temHistoryPassengerFlow);
                    }
                });
            }

            return historyPassengerFlows;
        }

        private HistoryPassengerFlow ConvertGateDayHistoryPassengerFlow(List<passengerflowbydate> passengerflows, DateTime startTime,DateTime endTime)
        {
            HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();

            IEnumerable<int?> inCounts = from t in passengerflows
                                         where t.isIn == true && t.historytime >=startTime
                                               && t.historytime <= endTime
                                         select t.count;
            IEnumerable<int?> outCounts = from t in passengerflows
                                          where t.isIn == false && t.historytime >=startTime
                                               && t.historytime <=endTime
                                          select t.count;

            historyPassengerFlow.InCount = inCounts.Sum().Value;
            historyPassengerFlow.OutCount = outCounts.Sum().Value;
            historyPassengerFlow.StrandedCount = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
            historyPassengerFlow.AllInOut = historyPassengerFlow.InCount + historyPassengerFlow.OutCount;
            historyPassengerFlow.Differ = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;

            return historyPassengerFlow;
        }

        #endregion

        #region 月报表分析

        public void RefreshMonthReport(bool isIn, DateTime dateTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            this.CurveTitle = GetMonthReportTitle(isSingleArea, isIn, dateTime);

            var getMonthPassengerQuery = m_Context.GetPassengerflowByMonthQuery(monitorAreaIDs, dateTime.Year, dateTime.Month);

            var loadMonthPassgnerQuery = m_Context.Load(getMonthPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var thisYearMonthPassneger = GetMonthHistoryPassengerFlow(isSingleArea, s.Entities, dateTime.Year, dateTime.Month);
                    var lastYearMonthPassenger = GetMonthHistoryPassengerFlow(isSingleArea, s.Entities, dateTime.Year - 1, dateTime.Month);
                    var thisHistoryPassenger = GetMonthHistoryPassengerFlow(isSingleArea, s.Entities.ToList(), dateTime.Year, dateTime.Month);

                    m_Context.passengerflowbydates.Clear();

                    var getYearPassengerQuery = m_Context.GetPassengerflowByYearQuery(monitorAreaIDs, dateTime.Year);

                    var loadYearPassgnerQuery = m_Context.Load(getYearPassengerQuery, (t) =>
                    {
                        if (!t.HasError)
                        {
                            var thisYearPassneger = GetYearHistoryPassengerFlow(isSingleArea, t.Entities, dateTime.Year);
                            var lastYearPassenger = GetYearHistoryPassengerFlow(isSingleArea, t.Entities, dateTime.Year - 1);
                            var thisYearHistoryPassenger = GetMonthHistoryPassengerFlow(isSingleArea, t.Entities.ToList(), dateTime.Year, dateTime.Month);

                            var getPassengerAgeQuery = m_Context.GetPassengerAgeByMonthQuery(monitorAreaIDs, dateTime.Year, dateTime.Month);
                            var loadPassengerAgeQuery = m_Context.Load(getPassengerAgeQuery, (d) => {

                                if (!d.HasError)
                                {
                                    this.TempPassengerAges = d.Entities;
                                }

                                if (AppendMultiHistoryPassenger != null)
                                {
                                    AppendMultiHistoryPassenger(this.CurveTitle, isIn,
                                                                thisYearPassneger,
                                                                thisYearMonthPassneger,
                                                                lastYearPassenger,
                                                                lastYearMonthPassenger,
                                                                thisHistoryPassenger,
                                                                thisYearHistoryPassenger);
                                }
                            
                            }, true);
                        }
                    }, true);
                }
            }, true);

            //Set DateTime Query
            DateTime startTime = new DateTime(dateTime.Year, dateTime.Month, 1, 0, 0, 0);
            DateTime endTime = startTime.AddMonths(1);
            var getDurationPassengerQuery = m_Context.GetPassengerflowbySpecifiedTimeQuery(monitorAreaIDs, 30, startTime, endTime);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (a) =>
            {
                if (!a.HasError)
                {
                    var firstDurationPassengers = GetAnyDurationHistoryPassengerFlow(isSingleArea, a.Entities, startTime, endTime, null);
                    this.TempPassengerFlowByMin = a.Entities;
                    if (AppendHistoryPassengerFlow != null)
                    {
                        AppendHistoryPassengerFlow(string.Empty, isIn,
                                                   CombineHistoryPassengerFlow2OneDay(false, firstDurationPassengers),null);
                    }

                }
            },true);

        }

        public List<HistoryPassengerFlow> GetMonthPassengersByArea(DateTime dateTime, int areaID)
        {
            List<HistoryPassengerFlow> passengers = new List<HistoryPassengerFlow>();

            List<int> gateIds = GetGateIDsByArea(areaID);
            var areaPassengers = this.TempPassengerFlowByMin.Where(t => gateIds.Contains(t.gateID));
            DateTime startTime = new DateTime(dateTime.Year, dateTime.Month, 1, 0, 0, 0);
            DateTime endTime = startTime.AddMonths(1);

            passengers = GetAnyDurationHistoryPassengerFlow(false, areaPassengers, startTime, endTime, null);

            return passengers;
        }

        public List<HistoryPassengerFlow> GetMonthHistoryPassengerFlow(bool isSingleArea, IEnumerable<passengerflowbydate> entities, int year, int month)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbydate> tempPassengerFlows = new List<passengerflowbydate>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            historyPassengerFlows = ConvertMonthHistoryPassengerFlow(tempPassengerFlows, year, month);
            return historyPassengerFlows;
        }

        public string GetMonthReportTitle(bool isSingleArea, bool isIn, DateTime dateTime)
        {
            string title = dateTime.Year + "年" + dateTime.Month + "月 ";

            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        title = title +GetAreaName(topAreaGate.ID) + " 所有门面";
                    }
                    else
                    {
                        title = title + GetAreaName(topAreaGate.ID) + " 所选门面";
                    }
                }
            }
            else
            {
                title = title + "所选店铺";
            }
            title = title + "  每日客流比较";
            return title;
        }

        #endregion

        #region 月客流统计

        public void RefreshMonthDayStatistics(int year1, int month1, int year2, int month2)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            //this.CurveTitle = GetMonthReportTitle(isSingleArea, isIn, dateTime);

            var getMonthPassengerQuery = m_Context.GetPassengerflowByMultiMonthQuery(monitorAreaIDs, year1, month1, year2, month2);

            var loadMonthPassgnerQuery = m_Context.Load(getMonthPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var firstMonthDayPassneger = GetMonthHistoryPassengerFlow(isSingleArea, s.Entities, year1, month1);
                    var secondMonthDayPassenger = GetMonthHistoryPassengerFlow(isSingleArea, s.Entities, year2, month2);
                    int index = 0;
                    string firstDateStr = string.Empty;
                    string secDateStr = string.Empty;
                    if (firstMonthDayPassneger.Count >= secondMonthDayPassenger.Count)
                    {
                        while (index < firstMonthDayPassneger.Count)
                        {
                            firstDateStr = string.Format("{0:MM-dd}", firstMonthDayPassneger[index].HistoryTime);
                            if (index < secondMonthDayPassenger.Count)
                            {
                                secDateStr = string.Format("{0:MM-dd}", secondMonthDayPassenger[index].HistoryTime);
                            }
                            else
                            {
                                secDateStr = string.Empty;
                            }
                            firstMonthDayPassneger[index].DisplayValue = firstDateStr + "\r\n" + secDateStr;
                            if (index < secondMonthDayPassenger.Count)
                            {
                                secondMonthDayPassenger[index].DisplayValue = firstDateStr + "\r\n" + secDateStr;
                            }
                            index++;
                        }
                    }
                    else
                    {
                        while (index < secondMonthDayPassenger.Count)
                        {
                            secDateStr = string.Format("{0:MM-dd}", secondMonthDayPassenger[index].HistoryTime);
                            if (index < firstMonthDayPassneger.Count)
                            {
                                firstDateStr = string.Format("{0:MM-dd}", firstMonthDayPassneger[index].HistoryTime);
                            }
                            else
                            {
                                firstDateStr = string.Empty;
                            }
                            secondMonthDayPassenger[index].DisplayValue = firstDateStr + "\r\n" + secDateStr;
                            if (index < firstMonthDayPassneger.Count)
                            {
                                firstMonthDayPassneger[index].DisplayValue = firstDateStr + "\r\n" + secDateStr;
                            }
                            index++;
                        }
                    }

                    if (AppendHistoryPassengerFlow != null)
                    {
                        this.ComparePassengerFlows = GetComparePassengerFlow(firstMonthDayPassneger, secondMonthDayPassenger);
                        AppendHistoryPassengerFlow(string.Empty, true, firstMonthDayPassneger, secondMonthDayPassenger);
                    }
                }
            },true);

        }

        private List<ComparePassengerFlow> GetComparePassengerFlow(List<HistoryPassengerFlow> firstMonthDayPassneger,
                                                                   List<HistoryPassengerFlow> secondMonthDayPassenger)
        {
            int index = 0;
            string firstDateStr = string.Empty;
            string secDateStr = string.Empty;
            List<ComparePassengerFlow> comparePassengerFlows = new List<ComparePassengerFlow>();
            ComparePassengerFlow tempComparePassenger = null;
            decimal percent = 0;
            int allFirstIn = firstMonthDayPassneger.Sum(t => t.InCount);
            int allFirstOut = firstMonthDayPassneger.Sum(t => t.OutCount);
            int allSecIn = secondMonthDayPassenger.Sum(t => t.InCount);
            int allSecOut = secondMonthDayPassenger.Sum(t => t.OutCount);
            if (firstMonthDayPassneger.Count >= secondMonthDayPassenger.Count)
            {
                while (index < firstMonthDayPassneger.Count)
                {
                    firstDateStr = string.Format("{0:MM-dd}", firstMonthDayPassneger[index].HistoryTime);

                    tempComparePassenger = new ComparePassengerFlow();
                    tempComparePassenger.InCount = firstMonthDayPassneger[index].InCount;

                    percent = allFirstIn > 0 ? ((decimal)firstMonthDayPassneger[index].InCount / allFirstIn) * 100 : 0;
                    percent = Math.Round(percent, 2);
                    tempComparePassenger.InPercent = percent > 0 ? percent.ToString() + "%" : string.Empty;

                    tempComparePassenger.OutCount = firstMonthDayPassneger[index].OutCount;

                    percent = allFirstOut > 0 ? ((decimal)firstMonthDayPassneger[index].OutCount / allFirstOut) * 100 : 0;
                    percent = Math.Round(percent, 2);
                    tempComparePassenger.OutPercent = percent > 0 ? percent.ToString() + "%" : string.Empty;
                    tempComparePassenger.DisplayDate = firstDateStr;

                    if (index < secondMonthDayPassenger.Count)
                    {
                        tempComparePassenger.CompareInCount = secondMonthDayPassenger[index].InCount;
                        percent = allSecIn > 0 ? ((decimal)secondMonthDayPassenger[index].InCount / allSecIn) * 100 : 0;
                        percent = Math.Round(percent, 2);
                        tempComparePassenger.CompareInPercent = percent > 0 ? percent.ToString() + "%" : string.Empty;
                        tempComparePassenger.CompareOutCount = secondMonthDayPassenger[index].OutCount;
                        percent = allSecOut > 0 ? ((decimal)secondMonthDayPassenger[index].OutCount / allSecOut) * 100 : 0;
                        percent = Math.Round(percent, 2);
                        tempComparePassenger.CompareOutPercent = percent > 0 ? percent.ToString() + "%" : string.Empty;
                        secDateStr = string.Format("{0:MM-dd}", secondMonthDayPassenger[index].HistoryTime);
                        tempComparePassenger.CompareDate = secDateStr;
                    }
                    else
                    {
                        secDateStr = string.Empty;
                    }
                    comparePassengerFlows.Add(tempComparePassenger);
                    index++;
                }
            }
            else
            {
                while (index < secondMonthDayPassenger.Count)
                {
                    secDateStr = string.Format("{0:MM-dd}", secondMonthDayPassenger[index].HistoryTime);
                    tempComparePassenger = new ComparePassengerFlow();
                    tempComparePassenger.CompareInCount = secondMonthDayPassenger[index].InCount;

                    percent = allSecIn > 0 ? ((decimal)secondMonthDayPassenger[index].InCount / allSecIn) * 100 : 0;
                    percent = Math.Round(percent, 2);
                    tempComparePassenger.CompareInPercent = percent > 0 ? percent.ToString() + "%" : string.Empty;

                    tempComparePassenger.CompareOutCount = secondMonthDayPassenger[index].OutCount;

                    percent = allSecOut > 0 ? ((decimal)secondMonthDayPassenger[index].OutCount / allSecOut) * 100 : 0;
                    percent = Math.Round(percent, 2);
                    tempComparePassenger.CompareOutPercent = percent > 0 ? percent.ToString() + "%" : string.Empty;
                    tempComparePassenger.CompareDate = secDateStr;
                    if (index < firstMonthDayPassneger.Count)
                    {
                        tempComparePassenger.InCount = firstMonthDayPassneger[index].InCount;

                        percent = allFirstIn > 0 ? ((decimal)firstMonthDayPassneger[index].InCount / allFirstIn) * 100 : 0;
                        percent = Math.Round(percent, 2);
                        tempComparePassenger.InPercent = percent > 0 ? percent.ToString() + "%" : string.Empty;

                        tempComparePassenger.OutCount = firstMonthDayPassneger[index].OutCount;

                        percent = allFirstOut > 0 ? ((decimal)firstMonthDayPassneger[index].OutCount / allFirstOut) * 100 : 0;
                        percent = Math.Round(percent, 2);
                        tempComparePassenger.OutPercent = percent > 0 ? percent.ToString() + "%" : string.Empty;;
                        firstDateStr = string.Format("{0:MM-dd}", firstMonthDayPassneger[index].HistoryTime);
                        tempComparePassenger.DisplayDate = firstDateStr;
                    }
                    else
                    {
                        firstDateStr = string.Empty;
                    }
                    comparePassengerFlows.Add(tempComparePassenger);
                    index++;
                }
            }

            return comparePassengerFlows;
        }

        #endregion

        #region 月各店客流统计

        public void RefreshMonthDayShopStatistics(int year, int month)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            //this.CurveTitle = GetMonthReportTitle(isSingleArea, isIn, dateTime);

            var getMonthPassengerQuery = m_Context.GetPassengerflowByMonthQuery(monitorAreaIDs, year, month);

            var loadMonthPassgnerQuery = m_Context.Load(getMonthPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    //var firstMonthDayPassneger = GetMonthHistoryPassengerFlow(isSingleArea, s.Entities, year, month);

                    if (AppendHistoryPassengerFlow != null)
                    {
                        this.TempPassengerFlowByDate = s.Entities;
                        //this.ComparePassengerFlows = GetComparePassengerFlow(firstMonthDayPassneger, secondMonthDayPassenger);
                        AppendHistoryPassengerFlow(string.Empty, true, null, null);
                    }
                }
            }, true);

        }

        public List<HistoryPassengerFlow> GetMonthDayShopPassengerFlow(int areaID,int year,int month)
        {
            var ids = GetGateIDsByArea(areaID);
            List<passengerflowbydate> areaPassengerFlows = this.TempPassengerFlowByDate.Where(t => ids.Contains(t.gateID)).ToList();
            var areaHistoryPassengerFlows = ConvertMonthHistoryPassengerFlow(areaPassengerFlows, year, month);


            return areaHistoryPassengerFlows;
        }

        #endregion

        #region 月周日客流统计

        public void RefreshMonthWeekReport(bool isIn, DateTime dateTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            //this.CurveTitle = GetMonthReportTitle(isSingleArea, isIn, dateTime);

            //Set DateTime Query
            DateTime startTime = new DateTime(dateTime.Year, dateTime.Month, 1, 0, 0, 0);
            DateTime endTime = startTime.AddMonths(1);
            var getDurationPassengerQuery = m_Context.GetPassengerflowbySpecifiedTimeQuery(monitorAreaIDs, 30, startTime, endTime);
            var loadDuaraionPassgnerQuery = m_Context.Load(getDurationPassengerQuery, (a) =>
            {
                if (!a.HasError)
                {
                    var firstDurationPassengers = GetAnyDurationHistoryPassengerFlow(isSingleArea, a.Entities, startTime, endTime, null);
                    this.TempPassengerFlowByMin = a.Entities;
                    if (AppendHistoryPassengerFlow != null)
                    {
                        AppendHistoryPassengerFlow(string.Empty, isIn,
                                                   CombineHistoryPassengerFlow2OneDay(false, firstDurationPassengers), null);
                    }

                }
            }, true);

        }

        #endregion

        #region 各月客流统计对比

        public void RefreshEveryMonthStatisticsReport(bool isIn, DateTime startDate, DateTime endDate)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            this.CurveTitle = GetMonthYearReport(isSingleArea, startDate, endDate);
            var getMonthPassengerQuery = m_Context.GetPassengerflowByMonthYearQuery(monitorAreaIDs, startDate.Year, startDate.Month, endDate.Year, endDate.Month);


            var loadMonthPassgnerQuery = m_Context.Load(getMonthPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var thisYearPassneger = GetYearMonthHistoryPassengerFlow(isSingleArea, s.Entities, startDate,endDate);
                  //  var lastYearPassenger = GetYearHistoryPassengerFlow(isSingleArea, s.Entities, dateTime.Year - 1);

                    if (AppendHistoryPassengerFlow != null)
                    {
                        AppendHistoryPassengerFlow(this.CurveTitle, isIn, thisYearPassneger, null);
                    }
                }
            }, true);
        }

        public List<HistoryPassengerFlow> GetYearMonthHistoryPassengerFlow(bool isSingleArea, IEnumerable<passengerflowbydate> entities,DateTime startDate,DateTime endDate)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbydate> tempPassengerFlows = new List<passengerflowbydate>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            historyPassengerFlows = ConvertYearMonthHistoryPassengerFlow(tempPassengerFlows, startDate, endDate);
            return historyPassengerFlows;
        }

        private string GetMonthYearReport(bool isSingleArea, DateTime startDate, DateTime endDate)
        {
            string title = startDate.Year + "年" + startDate.Month + "月至" + endDate.Year + "年" + endDate.Month + "月";

            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        title = title + GetAreaName(topAreaGate.ID) + " 所有门面";
                    }
                    else
                    {
                        title = title + GetAreaName(topAreaGate.ID) + " 所选门面";
                    }
                }
            }
            else
            {
                title = title + "所选店铺";
            }
            title = title + "各月累计客流表";
            return title;
        }

        #endregion

        #region 月同期客流对比

        public void RefreshMonthCompareReport(bool isIn, DateTime dateTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            //this.CurveTitle = GetMonthReportTitle(isSingleArea, isIn, dateTime);

            var getYearPassengerQuery = m_Context.GetPassengerflowByYearQuery(monitorAreaIDs, dateTime.Year);

            var loadYearPassgnerQuery = m_Context.Load(getYearPassengerQuery, (t) =>
            {
                if (!t.HasError)
                {
                    var thisYearPassneger = GetYearHistoryPassengerFlow(isSingleArea, t.Entities, dateTime.Year);
                    var lastYearPassenger = GetYearHistoryPassengerFlow(isSingleArea, t.Entities, dateTime.Year - 1);
                    //var thisYearHistoryPassenger = GetMonthHistoryPassengerFlow(isSingleArea, t.Entities.ToList(), dateTime.Year, dateTime.Month);
                    if (AppendHistoryPassengerFlow != null)
                    {
                        AppendHistoryPassengerFlow(this.CurveTitle, isIn, thisYearPassneger, lastYearPassenger);
                    }
                }
            }, true);

        }
        #endregion

        #region 年报表分析

        public void RefreshYearReport(bool isIn, DateTime dateTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            this.CurveTitle = GetYearReportTitle(isIn, isSingleArea, dateTime.Year);
            var getMonthPassengerQuery = m_Context.GetPassengerflowByYearQuery(monitorAreaIDs, dateTime.Year);

            var loadMonthPassgnerQuery = m_Context.Load(getMonthPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var thisYearPassneger = GetYearHistoryPassengerFlow(isSingleArea,s.Entities, dateTime.Year);
                    var lastYearPassenger = GetYearHistoryPassengerFlow(isSingleArea,s.Entities, dateTime.Year - 1);

                    if (AppendHistoryPassengerFlow != null)
                    {
                        AppendHistoryPassengerFlow(this.CurveTitle, isIn, thisYearPassneger, lastYearPassenger);
                    }
                }
            }, true);
        }

        public List<HistoryPassengerFlow> GetYearHistoryPassengerFlow(bool isSingleArea, IEnumerable<passengerflowbydate> entities, int year)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbydate> tempPassengerFlows = new List<passengerflowbydate>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            historyPassengerFlows = ConvertYearHistoryPassengerFlow(tempPassengerFlows, year);
            return historyPassengerFlows;
        }

        public string GetYearReportTitle(bool isIn, bool isSingleArea, int year)
        {
            string title = year.ToString();

            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        title = title + GetAreaName(topAreaGate.ID) + " 所有门面";
                    }
                    else
                    {
                        title = title + GetAreaName(topAreaGate.ID) + " 所选门面";
                    }
                }
            }
            else
            {
                title = title + "所选店铺";
            }
            title = title + "各月客流统计";
            return title;
        
        }

        #endregion

        #region 年每日客流统计

        public void RefreshYearDayReport(int year)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
           // this.CurveTitle = GetYearReportTitle(isIn, isSingleArea, dateTime.Year);
            var getYearDayPassengerQuery = m_Context.GetPassengerflowByYearDayQuery(monitorAreaIDs,year);

            var loadMonthPassgnerQuery = m_Context.Load(getYearDayPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var yearDayPassneger = GetYearDayHistoryPassengerFlow(isSingleArea, s.Entities, year);
                    if (AppendHistoryPassengerFlow != null)
                    {
                        AppendHistoryPassengerFlow(string.Empty, true, yearDayPassneger, null);
                    }
                }
            }, true);
        }

        public List<HistoryPassengerFlow> GetYearDayHistoryPassengerFlow(bool isSingleArea, IEnumerable<passengerflowbydate> entities, int year)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbydate> tempPassengerFlows = new List<passengerflowbydate>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            historyPassengerFlows = ConvertYearDayHistoryPassengerFlow(tempPassengerFlows, year);
            return historyPassengerFlows;
        }

        private List<HistoryPassengerFlow> ConvertYearDayHistoryPassengerFlow(List<passengerflowbydate> passengerflows, int year)
        {
            List<HistoryPassengerFlow> monthRealTimePassengerFlow = new List<HistoryPassengerFlow>();
            DateTime startTime = new DateTime(year, 1, 1, 0, 0, 0);
            DateTime endTime = startTime.AddYears(1);
            int lastInCount = 0;
            int lastOutCount = 0;
            while (startTime < endTime)
            {
                HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();

                historyPassengerFlow.HistoryTime = startTime;
                historyPassengerFlow.MonthOrDayOrWeek = startTime.Month;
                historyPassengerFlow.DisplayValue = startTime.Day.ToString();
                historyPassengerFlow.DisplayTitle = GetMonthDisplayTitle(startTime.Month);
                IEnumerable<int?> inCounts = from t in passengerflows
                                             where t.dt == startTime.Day && t.historytime.Value.Month == startTime.Month && 
                                                   t.historytime.Value.Year == year && t.isIn == true
                                             select t.count;
                IEnumerable<int?> outCounts = from t in passengerflows
                                              where t.dt == startTime.Day && t.historytime.Value.Month == startTime.Month &&
                                                   t.historytime.Value.Year == year && t.isIn == false
                                              select t.count;

                historyPassengerFlow.InCount = inCounts.Sum().Value;
                historyPassengerFlow.OutCount = outCounts.Sum().Value;
                historyPassengerFlow.AccumulateInCount = lastInCount + historyPassengerFlow.InCount;
                historyPassengerFlow.AccumulateOutCount = lastInCount + historyPassengerFlow.OutCount;
                historyPassengerFlow.StrandedCount = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                historyPassengerFlow.AllInOut = historyPassengerFlow.InCount + historyPassengerFlow.OutCount;
                historyPassengerFlow.Differ = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                lastInCount = historyPassengerFlow.AccumulateInCount;
                lastOutCount = historyPassengerFlow.AccumulateOutCount;

                monthRealTimePassengerFlow.Add(historyPassengerFlow);
                startTime = startTime.AddDays(1);

            }

            return monthRealTimePassengerFlow;
        }

        #endregion

        public void UpdateCheckedAreas()
        {
            m_checkedAreas = this.AreaExtends.Where(a => a.IsSelected).ToList();
            m_checkedGates = this.MonitorAreaGateExts.Where(g => g.IsSelected).ToList();
        }

        private string GetCheckedGatesText()
        {
            string sRet = string.Empty;

            if (m_checkedGates != null && m_checkedGates.Count > 0)
            {
                if (m_checkedGates.Count == MonitorAreaGateExts.Count)
                {
                    sRet = "所有";
                }
                else
                {
                    StringBuilder sb = new StringBuilder();
                    m_checkedGates.ForEach(g =>
                    {
                        sb.AppendFormat(", {0}", g.Name);
                    });
                    sRet = sb.ToString().TrimStart(",".ToCharArray());
                }
            }

            return sRet;
        }

        #region 年各门统计分析

        public void RefreshYearGateReport(bool isIn, DateTime dateTime)
        {
            if (ResetHisotryChartEvent != null)
            {
                ResetHisotryChartEvent();
            }
            var selectAreaExt = this.AreaExtends.Where(a => a.IsSelected).ToList();
            List<int> monitorAreaIDs = new List<int>();
            selectAreaExt.each(s => { monitorAreaIDs.Add(s.ID); });
            bool isSingleArea = monitorAreaIDs.Count == 1 ? true : false;
            this.CurveTitle = GetYearReportTitle(isIn, isSingleArea, dateTime.Year);
            var getMonthPassengerQuery = m_Context.GetPassengerflowByYearQuery(monitorAreaIDs, dateTime.Year);

            var loadMonthPassgnerQuery = m_Context.Load(getMonthPassengerQuery, (s) =>
            {
                if (!s.HasError)
                {
                    var thisYearPassneger = GetYearHistoryPassengerFlow(isSingleArea, s.Entities, dateTime.Year);
                    this.TempPassengerFlowByDate = s.Entities;
                    if (AppendHistoryPassengerFlow != null)
                    {
                        AppendHistoryPassengerFlow(this.CurveTitle, isIn, thisYearPassneger, null);
                    }
                }
            }, true);
        }

        public List<HistoryPassengerFlow> GetYearHistoryPassengerFlowByGate(bool isSingleArea,int year, int id)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            if (isSingleArea)
            {
                var tempPassengerFlows = this.TempPassengerFlowByDate.Where(entity => id == entity.gateID).ToList();
                historyPassengerFlows = ConvertYearHistoryPassengerFlow(tempPassengerFlows, year);
            }
            else
            {
                var selectAreaExt= this.AreaExtends.Where(a => a.ID == id).FirstOrDefault();
                if(selectAreaExt != null)
                {
                    var ids = GetGateIDsByArea(selectAreaExt.ID);
                    var tempPassengerFlows = this.TempPassengerFlowByDate.Where(entity => ids.Contains(entity.gateID)).ToList();
                    historyPassengerFlows = ConvertYearHistoryPassengerFlow(tempPassengerFlows, year);
                }
            }
            return historyPassengerFlows;
        }

        #endregion

        #region Private Methods

        public string GetAreaName(int areaID)
        {
            return this.AreaExtends.Where(a => a.ID == areaID).First().Name;
        }

        public List<int> GetGateIDsByArea(int areaID)
        {
            List<int> ids = new List<int>();

            var area = this.AreaExtends.Where(a => a.ID == areaID).FirstOrDefault().Tag as area;
            if (area != null)
            {
                area.gates.each(g => { ids.Add(g.ID); });
            }
            return ids;
        }

        private List<HistoryPassengerFlow> ConvertMonthHistoryPassengerFlow(List<passengerflowbydate> passengerflows, int year, int month)
        {
            List<HistoryPassengerFlow> monthRealTimePassengerFlow = new List<HistoryPassengerFlow>();
            DateTime startTime = new DateTime(year, month, 1);
            DateTime endTime = startTime.AddMonths(1);
            int lastInCount = 0;
            int lastOutCount = 0;
            while (startTime < endTime)
            {
                HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();

                historyPassengerFlow.HistoryTime = startTime;
                historyPassengerFlow.MonthOrDayOrWeek = startTime.Day;
                IEnumerable<int?> inCounts = from t in passengerflows
                                             where t.dt.Value == startTime.Day && t.historytime.Value.Month == month 
                                                   && t.historytime.Value.Year == year && t.isIn == true
                                             select t.count;
                IEnumerable<int?> outCounts = from t in passengerflows
                                              where t.dt.Value == startTime.Day && t.historytime.Value.Month == month 
                                                   && t.historytime.Value.Year == year && t.isIn == false
                                              select t.count;

                historyPassengerFlow.InCount = inCounts.Sum().Value;
                historyPassengerFlow.OutCount = outCounts.Sum().Value;
                historyPassengerFlow.AccumulateInCount = lastInCount + historyPassengerFlow.InCount;
                historyPassengerFlow.AccumulateOutCount = lastInCount + historyPassengerFlow.OutCount;
                historyPassengerFlow.StrandedCount = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                historyPassengerFlow.AllInOut = historyPassengerFlow.InCount + historyPassengerFlow.OutCount;
                historyPassengerFlow.Differ = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                lastInCount = historyPassengerFlow.AccumulateInCount;
                lastOutCount = historyPassengerFlow.AccumulateOutCount;

                monthRealTimePassengerFlow.Add(historyPassengerFlow);
                startTime = startTime.AddDays(1);

            }

            return monthRealTimePassengerFlow;
        }

        private List<HistoryPassengerFlow> ConvertYearHistoryPassengerFlow(List<passengerflowbydate> passengerflows, int year)
        {
            List<HistoryPassengerFlow> monthRealTimePassengerFlow = new List<HistoryPassengerFlow>();
            DateTime startTime = new DateTime(year, 1, 1);
            DateTime endTime = startTime.AddYears(1);
            int lastInCount = 0;
            int lastOutCount = 0;
            while (startTime < endTime)
            {
                HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();

                historyPassengerFlow.HistoryTime = startTime;
                historyPassengerFlow.MonthOrDayOrWeek = startTime.Month;
                historyPassengerFlow.DisplayTitle = GetMonthDisplayTitle(startTime.Month);
                IEnumerable<int?> inCounts = from t in passengerflows
                                             where t.dt == startTime.Month && t.historytime.Value.Year == year && t.isIn == true
                                             select t.count;
                IEnumerable<int?> outCounts = from t in passengerflows
                                              where t.dt == startTime.Month && t.historytime.Value.Year == year && t.isIn == false
                                              select t.count;

                historyPassengerFlow.InCount = inCounts.Sum().Value;
                historyPassengerFlow.OutCount = outCounts.Sum().Value;
                historyPassengerFlow.AccumulateInCount = lastInCount + historyPassengerFlow.InCount;
                historyPassengerFlow.AccumulateOutCount = lastInCount + historyPassengerFlow.OutCount;
                historyPassengerFlow.StrandedCount = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                historyPassengerFlow.AllInOut = historyPassengerFlow.InCount + historyPassengerFlow.OutCount;
                historyPassengerFlow.Differ = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                lastInCount = historyPassengerFlow.AccumulateInCount;
                lastOutCount = historyPassengerFlow.AccumulateOutCount;

                monthRealTimePassengerFlow.Add(historyPassengerFlow);
                startTime = startTime.AddMonths(1);

            }

            return monthRealTimePassengerFlow;
        }

        private List<HistoryPassengerFlow> ConvertYearMonthHistoryPassengerFlow(List<passengerflowbydate> passengerflows, DateTime startDate, DateTime endDate)
        {
            List<HistoryPassengerFlow> monthRealTimePassengerFlow = new List<HistoryPassengerFlow>();
            DateTime startTime = startDate;
            DateTime endTime = endDate.AddMonths(1);
            int lastInCount = 0;
            int lastOutCount = 0;
            while (startTime < endTime)
            {
                HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();

                historyPassengerFlow.HistoryTime = startTime;
                historyPassengerFlow.MonthOrDayOrWeek = startTime.Month;
                historyPassengerFlow.DisplayTitle = startTime.Year + "年" + startTime.Month + "月";
                IEnumerable<int?> inCounts = from t in passengerflows
                                             where t.dt == startTime.Month && t.historytime.Value.Year == startTime.Year && t.isIn == true
                                             select t.count;
                IEnumerable<int?> outCounts = from t in passengerflows
                                              where t.dt == startTime.Month && t.historytime.Value.Year == startTime.Year && t.isIn == false
                                              select t.count;

                historyPassengerFlow.InCount = inCounts.Sum().Value;
                historyPassengerFlow.OutCount = outCounts.Sum().Value;
                historyPassengerFlow.AccumulateInCount = lastInCount + historyPassengerFlow.InCount;
                historyPassengerFlow.AccumulateOutCount = lastInCount + historyPassengerFlow.OutCount;
                historyPassengerFlow.StrandedCount = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                historyPassengerFlow.AllInOut = historyPassengerFlow.InCount + historyPassengerFlow.OutCount;
                historyPassengerFlow.Differ = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                lastInCount = historyPassengerFlow.AccumulateInCount;
                lastOutCount = historyPassengerFlow.AccumulateOutCount;

                monthRealTimePassengerFlow.Add(historyPassengerFlow);
                startTime = startTime.AddMonths(1);

            }

            return monthRealTimePassengerFlow;
        }

        private string GetMonthDisplayTitle(int month)
        {
            string monthName = "一月";

            switch (month)
            {
                case 1:
                    monthName = "一月";
                    break;
                case 2:
                    monthName = "二月";
                    break;
                case 3:
                    monthName = "三月";
                    break;
                case 4:
                    monthName = "四月";
                    break;
                case 5:
                    monthName = "五月";
                    break;
                case 6:
                    monthName = "六月";
                    break;
                case 7:
                    monthName = "七月";
                    break;
                case 8:
                    monthName = "八月";
                    break;
                case 9:
                    monthName = "九月";
                    break;
                case 10:
                    monthName = "十月";
                    break;
                case 11:
                    monthName = "十一月";
                    break;
                case 12:
                    monthName = "十二月";
                    break;

            }

            return monthName;
        }

        private List<HistoryPassengerFlow> GetMonthHistoryPassengerFlow(bool isSingleArea,List<passengerflowbydate> passengerflows,int year,int month)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            HistoryPassengerFlow temHistoryPassengerFlow = null;
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    ids.each(id =>
                    {
                        var tempPassengerFlows = passengerflows.Where(entity => id == entity.gateID).ToList();
                        temHistoryPassengerFlow = ConvertHistoryPassengerFlow(tempPassengerFlows,year,month);
                        if (temHistoryPassengerFlow != null)
                        {
                            temHistoryPassengerFlow.DisplayTitle = GetGateName(id);
                            historyPassengerFlows.Add(temHistoryPassengerFlow);
                        }
                        
                    });
                }
            }
            else
            {
                var selectAreaExts = this.AreaExtends.Where(a => a.IsSelected).ToList();
                selectAreaExts.each(s => {
                    var ids = GetGateIDsByArea(s.ID);
                    var tempPassengerFlows = passengerflows.Where(entity => ids.Contains(entity.gateID)).ToList();
                    temHistoryPassengerFlow = ConvertHistoryPassengerFlow(tempPassengerFlows,year,month);
                    if (temHistoryPassengerFlow != null)
                    {
                        temHistoryPassengerFlow.DisplayTitle = s.Name;
                        historyPassengerFlows.Add(temHistoryPassengerFlow);
                    }
                });
            }

            return historyPassengerFlows;
        }

        private HistoryPassengerFlow ConvertHistoryPassengerFlow(List<passengerflowbydate> passengerflows,int year,int month)
        {
            HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();

            IEnumerable<int?> inCounts = from t in passengerflows
                                         where t.isIn == true && t.historytime.Value.Year == year
                                               && t.historytime.Value.Month == month
                                         select t.count;
            IEnumerable<int?> outCounts = from t in passengerflows
                                          where t.isIn == false && t.historytime.Value.Year == year
                                               && t.historytime.Value.Month == month
                                          select t.count;

            historyPassengerFlow.InCount = inCounts.Sum().Value;
            historyPassengerFlow.OutCount = outCounts.Sum().Value;
            historyPassengerFlow.StrandedCount = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
            historyPassengerFlow.AllInOut = historyPassengerFlow.InCount + historyPassengerFlow.OutCount;
            historyPassengerFlow.Differ = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;

            return historyPassengerFlow;
        }

        public string GetGateName(int id)
        {
            string title = string.Empty;

            var a = this.MonitorAreaGateExts.Where(m => m.ID == id).FirstOrDefault();
            if (a != null)
            {
                title = a.Name;
            }

            return title;
        }

        /// <summary>
        /// 补齐固定间隔记录， 如果没有， 填充一条空的记录
        /// </summary>
        /// <param name="passengerflows"></param>
        /// <param name="minsInterval"></param>
        /// <param name="dtRangeStart"></param>
        /// <param name="dtRangeEnd"></param>
        /// <param name="enableWeeks"></param>
        /// <returns></returns>
        private List<HistoryPassengerFlow> ComplementHistoryPassengerFlow(List<passengerflowbymin> passengerflows,
                                                                       int minsInterval,
                                                                       DateTime dtRangeStart,
                                                                       DateTime dtRangeEnd,
                                                                       List<DayOfWeek> enableWeeks)
        {
            List<HistoryPassengerFlow> dayRealTimePassengerFlow = new List<HistoryPassengerFlow>();
            DateTime startTime = dtRangeStart;
            DateTime dtTmp;
            int lastInCount = 0;
            int lastOutCount = 0;
            bool isIncludeWeek = true;
            while (startTime < dtRangeEnd)
            {
                if (enableWeeks != null && enableWeeks.Count > 0)
                {
                    if (enableWeeks.Contains(startTime.DayOfWeek))
                    {
                        isIncludeWeek = true;
                    }
                    else
                    {
                        isIncludeWeek = false;
                    }
                }
                else
                {
                    isIncludeWeek = true;
                }
                if (isIncludeWeek)
                {
                    HistoryPassengerFlow historyPassengerFlow = new HistoryPassengerFlow();
                    //historyPassengerFlow.DisplayTitle = dtRangeStart.ToShortDateString() + " 至 " + dtRangeEnd.ToShortDateString();
                    historyPassengerFlow.HistoryTime = startTime;
                    IEnumerable<int?> inCounts = from t in passengerflows
                                                 where t.dt == startTime && t.isIn == true
                                                 select t.count;
                    IEnumerable<int?> outCounts = from t in passengerflows
                                                  where t.dt == startTime && t.isIn == false
                                                  select t.count;

                    historyPassengerFlow.InCount = inCounts.Sum().Value;
                    historyPassengerFlow.OutCount = outCounts.Sum().Value;
                    historyPassengerFlow.AccumulateInCount = lastInCount + historyPassengerFlow.InCount;
                    historyPassengerFlow.AccumulateOutCount = lastOutCount + historyPassengerFlow.OutCount;
                    // historyPassengerFlow.StrandedCount = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                    historyPassengerFlow.StrandedCount = historyPassengerFlow.AccumulateInCount - historyPassengerFlow.AccumulateOutCount;
                    historyPassengerFlow.AllInOut = historyPassengerFlow.InCount + historyPassengerFlow.OutCount;
                    historyPassengerFlow.Differ = historyPassengerFlow.InCount - historyPassengerFlow.OutCount;
                    lastInCount = historyPassengerFlow.AccumulateInCount;
                    lastOutCount = historyPassengerFlow.AccumulateOutCount;

                    Debug.WriteLine("ComplementHistoryPassengerFlow: {0}: in: {1}, Out: {2}, Sub total in: {3}, Sub total  out: {4}, Retain: {5}",
                        historyPassengerFlow.HistoryTime,
                        historyPassengerFlow.InCount, historyPassengerFlow.OutCount,
                        historyPassengerFlow.AccumulateInCount, historyPassengerFlow.AccumulateOutCount, historyPassengerFlow.StrandedCount);

                    dayRealTimePassengerFlow.Add(historyPassengerFlow);
                }
                
                dtTmp = startTime.AddMinutes(minsInterval);

                if (startTime.Day != dtTmp.Day)
                {
                    lastInCount = lastOutCount = 0;
                }
                startTime = dtTmp;
            }
            return dayRealTimePassengerFlow;
        }

        private List<HistoryPassengerFlow> GetAnyDurationHistoryPassengerFlow(bool isSingleArea,
                                                                                    IEnumerable<passengerflowbymin> entities,
                                                                                    DateTime startTime,
                                                                                    DateTime endTime,
                                                                                    List<DayOfWeek> enbaleWeeks)
        {
            List<HistoryPassengerFlow> historyPassengerFlows = new List<HistoryPassengerFlow>();
            List<passengerflowbymin> tempPassengerFlows = new List<passengerflowbymin>();
            if (isSingleArea)
            {
                var topAreaGate = this.MonitorAreaGateExts.Where(m => m.TypeID == 1).FirstOrDefault();
                if (topAreaGate != null)
                {
                    List<int> ids = new List<int>();
                    if (topAreaGate.IsSelected)
                    {
                        ids = GetGateIDsByArea(topAreaGate.ID);
                    }
                    else
                    {
                        ids = this.MonitorAreaGateExts.Where(m => m.IsSelected && m.TypeID != 1).Select(mm => mm.ID).ToList();
                    }
                    tempPassengerFlows = entities.Where(entity => ids.Contains(entity.gateID)).ToList();
                }
            }
            else
            {
                tempPassengerFlows = entities.ToList();
            }

            //补齐每隔半小时缺少的记录
            historyPassengerFlows = ComplementHistoryPassengerFlow(tempPassengerFlows, 30, startTime, endTime, enbaleWeeks);

            return historyPassengerFlows;
        }

        /// <summary>
        /// Mapping the records to one day
        /// </summary>
        /// <param name="isAvg"></param>
        /// <param name="historyPassengerFlow"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <returns></returns>
        private List<HistoryPassengerFlow> CombineHistoryPassengerFlow2OneDay(bool isAvg, List<HistoryPassengerFlow> historyPassengerFlow)
        {
            List<HistoryPassengerFlow> computedHistoryPassengerFlow = new List<HistoryPassengerFlow>();

            DateTime startTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);
            DateTime endTime = startTime.AddDays(1);

            while (startTime < endTime)
            {
                HistoryPassengerFlow tempPassgnegerFlow = new HistoryPassengerFlow();
                //historyPassengerFlow.DisplayTitle = dtRangeStart.ToShortDateString() + " 至 " + dtRangeEnd.ToShortDateString();
                tempPassgnegerFlow.HistoryTime = startTime;

                IEnumerable<HistoryPassengerFlow> hpfsByDateTime = from t in historyPassengerFlow
                                                                   where t.HistoryTime.Hour == startTime.Hour &&
                                                                         t.HistoryTime.Minute == startTime.Minute &&
                                                                         t.HistoryTime.Second == startTime.Second
                                                                   select t;

                IEnumerable<int> inCounts = from t in historyPassengerFlow
                                            where t.HistoryTime.Hour == startTime.Hour &&
                                                  t.HistoryTime.Minute == startTime.Minute &&
                                                  t.HistoryTime.Second == startTime.Second
                                            select t.InCount;
                IEnumerable<int> outCounts = from t in historyPassengerFlow
                                             where t.HistoryTime.Hour == startTime.Hour &&
                                                 t.HistoryTime.Minute == startTime.Minute &&
                                                 t.HistoryTime.Second == startTime.Second
                                             select t.OutCount;
                IEnumerable<int> strandedCount = from t in historyPassengerFlow
                                                 where t.HistoryTime.Hour == startTime.Hour &&
                                                  t.HistoryTime.Minute == startTime.Minute &&
                                                  t.HistoryTime.Second == startTime.Second
                                                 select t.StrandedCount;
                tempPassgnegerFlow.InCount = 
                    hpfsByDateTime.Any() ? (isAvg ? Convert.ToInt32(hpfsByDateTime.Average(s => s.InCount)) : hpfsByDateTime.Sum(s => s.InCount)) : 0;
                tempPassgnegerFlow.OutCount = 
                    hpfsByDateTime.Any() ? (isAvg ? Convert.ToInt32(hpfsByDateTime.Average(s => s.InCount)) : hpfsByDateTime.Sum(s => s.InCount)) : 0;
                tempPassgnegerFlow.AccumulateInCount = 
                    hpfsByDateTime.Any() ? (isAvg ? Convert.ToInt32(hpfsByDateTime.Average(s => s.AccumulateInCount)) : hpfsByDateTime.Sum(s => s.AccumulateInCount)) : 0;
                tempPassgnegerFlow.AccumulateOutCount = 
                    hpfsByDateTime.Any() ? (isAvg ? Convert.ToInt32(hpfsByDateTime.Average(s => s.AccumulateOutCount)) : hpfsByDateTime.Sum(s => s.AccumulateOutCount)) : 0;
                tempPassgnegerFlow.AllInOut = 
                    hpfsByDateTime.Any() ? (isAvg ? Convert.ToInt32(hpfsByDateTime.Average(s => s.AllInOut)) : hpfsByDateTime.Sum(s => s.AllInOut)) : 0;
                tempPassgnegerFlow.StrandedCount =
                    hpfsByDateTime.Any() ? (isAvg ? Convert.ToInt32(hpfsByDateTime.Average(s => s.StrandedCount)) : hpfsByDateTime.Sum(s => s.StrandedCount)) : 0;

                computedHistoryPassengerFlow.Add(tempPassgnegerFlow);
                startTime = startTime.AddMinutes(30);

            }

            return computedHistoryPassengerFlow;
        }

        public void GetWeekStartAndEndTime(DateTime dateTime, out DateTime startTime, out DateTime endTime)
        {
            startTime = dateTime;
            endTime = dateTime;
            switch (dateTime.DayOfWeek)
            {
                case DayOfWeek.Sunday:
                    endTime = dateTime.AddDays(1);
                    startTime = dateTime.AddDays(-6);
                    break;
                case DayOfWeek.Monday:
                    startTime = dateTime;
                    endTime = dateTime.AddDays(7);
                    break;
                case DayOfWeek.Tuesday:
                    startTime = dateTime.AddDays(-1);
                    endTime = dateTime.AddDays(6);
                    break;
                case DayOfWeek.Wednesday:
                    startTime = dateTime.AddDays(-2);
                    endTime = dateTime.AddDays(5);
                    break;
                case DayOfWeek.Thursday:
                    startTime = dateTime.AddDays(-3);
                    endTime = dateTime.AddDays(4);
                    break;
                case DayOfWeek.Friday:
                    startTime = dateTime.AddDays(-4);
                    endTime = dateTime.AddDays(3);
                    break;
                case DayOfWeek.Saturday:
                    startTime = dateTime.AddDays(-5);
                    endTime = dateTime.AddDays(2);
                    break;
            }
        }

        #endregion

        #region INotifyPropertyChanged Interface

        public event PropertyChangedEventHandler PropertyChanged;
        public void NofityPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }
}
